<template>
  <view class="container">
    <view class="header">
      <view class="back-btn" @tap="goBack">
        <text class="iconfont icon-back"></text>
      </view>
      <text class="title">{{ isFaceRegistration ? '人脸识别录入' : '人脸识别登录' }}</text>
    </view>
    
    <view class="face-scan">
      <view class="scan-area" :class="{ scanning: isScanning, recognized: isRecognized, failed: isFaceFailed }">
        <!-- 摄像头视图组件 -->
        <camera v-if="isScanning && !isRecognized" device-position="front" flash="off" class="camera" @error="handleCameraError"></camera>
        
        <view class="scan-frame">
          <view class="corner top-left"></view>
          <view class="corner top-right"></view>
          <view class="corner bottom-left"></view>
          <view class="corner bottom-right"></view>
          
          <view class="scan-line" v-if="isScanning"></view>
          <view class="countdown-timer" v-if="isScanning && countdownValue > 0">
            <text>{{ countdownValue }}</text>
          </view>
          <view class="face-avatar" v-if="isRecognized || isFaceFailed">
            <image :src="faceImage || '/static/images/avatar.gif'"></image>
          </view>
        </view>
        
        <text class="scan-tips">{{ scanTips }}</text>
      </view>
      
      <view class="action-btns">
        <button class="action-btn primary" @tap="startScan" v-if="!isScanning && !isRecognized && !isFaceFailed">
          开始扫描
        </button>
        <button class="action-btn cancel" @tap="cancelScan" v-if="isScanning">
          取消
        </button>
        <button class="action-btn primary" @tap="confirmFaceAction" v-if="isRecognized">
          {{ isFaceRegistration ? '确认录入' : '确认登录' }}
        </button>
        <button class="action-btn retry" @tap="retryCapture" v-if="isFaceFailed || isRecognized">
          重新拍照
        </button>
      </view>
      
      <view class="tips">
        <text>{{ isFaceRegistration ? '录入人脸信息，下次可直接登录' : '请确保光线充足，面部无遮挡' }}</text>
        <text>面部需清晰可见，不要佩戴墨镜等饰品</text>
      </view>
      
      <view class="switch-mode" @tap="switchMode">
        <text>{{ isFaceRegistration ? '已有人脸信息？点此登录' : '首次使用？点此录入人脸' }}</text>
      </view>
    </view>
  </view>
</template>

<script>
import request from '@/utils/request'
import { BASE_URL, SERVICE_PREFIX } from '@/utils/request'

export default {
  data() {
    return {
      isScanning: false,
      isRecognized: false,
      isFaceFailed: false,  // 是否人脸录入失败
      isFaceRegistration: false,  // 是否为人脸录入模式
      scanTips: '请将脸部放入框内',
      faceImage: '',
      scanTimeout: null,
      countdownTimer: null,
      countdownValue: 0,
      cameraContext: null,
      userType: 'student', // 默认为学生用户
      isProcessingLogin: false // 是否正在处理登录
    }
  },
  onLoad(options) {
    // 检查用户是否已登录，如果已登录直接跳转到首页
    const token = uni.getStorageSync('token');
    const userInfo = uni.getStorageSync('userInfo');
    
    if (token && userInfo) {
      // 用户已登录，直接跳转到首页
      uni.reLaunch({
        url: '/pages/index/index'
      });
      return;
    }
    
    // 检查是否是人脸录入模式
    if (options.mode === 'register') {
      this.isFaceRegistration = true;
    }
    
    // 检查用户类型
    if (options.userType === 'faculty') {
      this.userType = 'faculty';
    }
    
    // 创建相机上下文
    this.cameraContext = uni.createCameraContext();
  },
  onUnload() {
    // 清除定时器
    this.clearTimers();
  },
  methods: {
    clearTimers() {
      if (this.scanTimeout) {
        clearTimeout(this.scanTimeout);
        this.scanTimeout = null;
      }
      if (this.countdownTimer) {
        clearInterval(this.countdownTimer);
        this.countdownTimer = null;
      }
    },
    
    goBack() {
      uni.navigateBack();
    },
    
    switchMode() {
      this.isFaceRegistration = !this.isFaceRegistration;
      this.isScanning = false;
      this.isRecognized = false;
      this.isFaceFailed = false;
      this.faceImage = '';
      this.scanTips = '请将脸部放入框内';
      this.countdownValue = 0;
      this.clearTimers();
    },
    
    startScan() {
      // 请求摄像头权限
      uni.authorize({
        scope: 'scope.camera',
        success: () => {
          this.isScanning = true;
          this.scanTips = '准备扫描人脸，请保持面部在框内';
          
          // 直接开始倒计时
          this.startCountdown();
        },
        fail: () => {
          uni.showModal({
            title: '提示',
            content: '您拒绝了摄像头权限，无法进行人脸识别',
            showCancel: false
          });
        }
      });
    },
    
    startCountdown() {
      // 设置倒计时初始值
      this.countdownValue = 5;
      this.scanTips = `准备拍照，倒计时 ${this.countdownValue} 秒`;
      
      // 创建倒计时定时器
      this.countdownTimer = setInterval(() => {
        this.countdownValue--;
        this.scanTips = `准备拍照，倒计时 ${this.countdownValue} 秒`;
        
        if (this.countdownValue <= 0) {
          // 清除倒计时定时器
          clearInterval(this.countdownTimer);
          this.countdownTimer = null;
          
          // 执行拍照
          this.takePhoto();
        }
      }, 1000);
    },
    
    takePhoto() {
      if (!this.cameraContext) {
        this.cameraContext = uni.createCameraContext();
      }
      
      this.scanTips = '拍照中...';
      
      // 调用摄像头拍照
      this.cameraContext.takePhoto({
        quality: 'high',
        success: (res) => {
          // 拍照成功，获取图片路径
          this.faceImage = res.tempImagePath;
          
          // 标记为识别成功状态
          this.isScanning = false;
          this.isRecognized = true;
          this.isFaceFailed = false;
          this.scanTips = this.isFaceRegistration ? '人脸捕获成功' : '人脸捕获成功';
          
          // 自动确认操作，不需要用户二次确认
          setTimeout(() => {
            this.confirmFaceAction();
          }, 1000);
        },
        fail: (err) => {
          console.error('拍照失败:', err);
          
          uni.showToast({
            title: '拍照失败，请重试',
            icon: 'none'
          });
        }
      });
    },
    
    // 重新拍照功能
    retryCapture() {
      this.isRecognized = false;
      this.isFaceFailed = false;
      this.faceImage = '';
      this.scanTips = '请对准人脸重新拍照';
      this.countdownValue = 0;
      this.clearTimers();
      this.startScan();
    },
    
    handleCameraError(e) {
      console.error('相机错误:', e);
      this.cancelScan();
      
      uni.showModal({
        title: '相机错误',
        content: '无法启动相机，请检查权限或重试',
        showCancel: false
      });
    },
    
    cancelScan() {
      this.clearTimers();
      this.isScanning = false;
      this.countdownValue = 0;
      this.scanTips = '请将脸部放入框内';
    },
    
    confirmFaceAction() {
      if (!this.faceImage) {
        uni.showToast({
          title: '请先拍摄人脸照片',
          icon: 'none'
        });
        return;
      }
      
      // 根据当前模式决定调用的接口
      if (this.isFaceRegistration) {
        this.uploadFace();
      } else {
        this.faceLogin();
      }
    },
    
    // 人脸录入
    uploadFace() {
      // 显示加载提示
      uni.showLoading({
        title: '上传中...'
      });
      
      // 上传图片到服务器
      uni.uploadFile({
        url: BASE_URL + '/api/teacher/uploadFace',
        filePath: this.faceImage,
        name: 'faceImage',
        header: {
          'token': uni.getStorageSync('token') || ''
        },
        formData: {
          userId: uni.getStorageSync('userInfo')?.userId || '',
          userType: this.userType
        },
        success: (res) => {
          uni.hideLoading();
          
          try {
            const response = JSON.parse(res.data);
            console.log('人脸录入响应:', response);
            
            if (response.code === 200) {
              uni.showToast({
                title: '人脸录入成功',
                icon: 'success',
                duration: 1500
              });
              
              // 延迟返回登录页
              setTimeout(() => {
                uni.redirectTo({
                  url: '/pages/login/login'
                });
              }, 1500);
            } else {
              // 处理错误 - 使用安全的消息提取方式
              let errorMsg = '人脸录入失败';
              
              // 根据状态码和消息内容判断具体错误
              if (response.code === 400) {
                if (response.message && response.message.includes('未检测')) {
                  errorMsg = '未检测到人脸';
                } else if (response.message && response.message.includes('相似度')) {
                  errorMsg = '人脸已存在，无需重复录入';
                } else if (response.message && response.message.includes('空')) {
                  errorMsg = '上传图片不能为空';
                }
              }
              
              this.handleFaceUploadFail(errorMsg);
            }
          } catch (error) {
            console.error('解析响应失败:', error);
            this.handleFaceUploadFail('解析响应失败');
          }
        },
        fail: (err) => {
          uni.hideLoading();
          this.handleFaceUploadFail('上传失败');
        }
      });
    },
    
    // 人脸登录
    faceLogin() {
      // 如果正在处理登录，防止重复调用
      if (this.isProcessingLogin) {
        return;
      }
      
      this.isProcessingLogin = true;
      
      // 显示加载提示
      uni.showLoading({
        title: '识别中...'
      });
      
      // 上传图片到服务器进行人脸识别
      uni.uploadFile({
        url: BASE_URL + '/api/teacher/faceLogin',
        filePath: this.faceImage,
        name: 'faceImage',
        formData: {
          userType: this.userType
        },
        success: (res) => {
          uni.hideLoading();
          this.isProcessingLogin = false;
          
          try {
            console.log('API响应原始数据:', res.data);
            const response = JSON.parse(res.data);
            console.log('API响应解析后:', response);
            console.log('响应状态码:', response.code);
            console.log('响应消息:', response.message);
            console.log('响应数据结构:', response.data);
            
            // 检查响应状态码
            if (response.code === 200 && response.data) {
              // 直接使用默认消息，避免解码问题
              let message = '识别成功，欢迎！';
              
              // 记录返回的用户数据，方便调试
              console.log('用户数据详情:');
              if (response.data) {
                Object.keys(response.data).forEach(key => {
                  console.log(`${key}: ${response.data[key]}`);
                });
              }
              
              // 确保用户ID是有效的
              if (!response.data.userId) {
                console.error('API返回的用户ID为空');
                this.handleFaceUploadFail('登录异常：用户信息不完整');
                return;
              }
              
              // 构建完整的用户信息对象
              const userInfo = {
                userId: response.data.userId,
                username: response.data.username || '',
                nickname: response.data.nickname || response.data.username || '用户' + response.data.userId,
                avatarUrl: response.data.avatarUrl || '',
                signature: response.data.signature || '',
                phone: response.data.phone || '',
                email: response.data.email || '',
                gender: response.data.gender || null,
                // 其他可能的属性
                likes: response.data.likes || 0,
                following: response.data.following || 0,
                followers: response.data.followers || 0
              };
              
              // 保存token - 后端可能没有返回token，我们自己生成一个
              const token = response.data.token || 'face_login_token_' + response.data.userId + '_' + new Date().getTime();
              console.log('设置token:', token);
              uni.setStorageSync('token', token);
              
              // 明确标记用户已登录
              uni.setStorageSync('isGuest', false);
              
              // 保存用户信息
              uni.setStorageSync('userInfo', userInfo);
              
              // 保存用户类型
              uni.setStorageSync('userType', this.userType);
              
              // 输出保存的信息，用于调试
              console.log('保存的用户信息:', userInfo);
              console.log('保存的token:', token);
              console.log('保存的用户类型:', this.userType);
              console.log('保存的isGuest状态:', false);
              
              // 设置识别成功的UI状态
              this.scanTips = message;
              this.isRecognized = true;
              
              // 显示成功提示
              uni.showToast({
                title: '登录成功',
                icon: 'success',
                duration: 1500
              });
              
              // 立即跳转到首页，不再等待
                uni.reLaunch({
                  url: '/pages/index/index'
                });
            } else {
              // 处理错误 - 使用安全的消息提取方式
              let errorMsg = '人脸识别失败';
              
              // 不再尝试复杂的解码，直接使用固定消息
              if (response.code === 400) {
                if (response.message && response.message.includes('录入')) {
                  errorMsg = '请先录入人脸';
                } else if (response.message && response.message.includes('检测')) {
                  errorMsg = '未检测到人脸';
                }
              }
              
              this.handleFaceUploadFail(errorMsg);
            }
          } catch (error) {
            console.error('解析响应失败:', error);
            this.handleFaceUploadFail('解析响应失败');
          }
        },
        fail: (err) => {
          console.error('请求失败:', err);
          uni.hideLoading();
          this.isProcessingLogin = false;
          this.handleFaceUploadFail('网络请求失败');
        }
      });
    },
    
    handleFaceUploadFail(message) {
      this.isRecognized = false;
      this.isFaceFailed = true;
      this.scanTips = message;
      
      uni.showToast({
        title: message,
        icon: 'none'
      });
    }
  }
}
</script>

<style lang="scss">
.container {
  min-height: 100vh;
  background: #fff;
  display: flex;
  flex-direction: column;
}

.header {
  display: flex;
  align-items: center;
  height: 100rpx;
  padding: 0 30rpx;
  position: relative;
  
  .back-btn {
    width: 80rpx;
    height: 80rpx;
    display: flex;
    align-items: center;
    justify-content: center;
    
    .iconfont {
      font-size: 40rpx;
      color: #333;
    }
  }
  
  .title {
    position: absolute;
    left: 0;
    right: 0;
    text-align: center;
    font-size: 36rpx;
    font-weight: bold;
    color: #333;
  }
}

.face-scan {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 40rpx;
  
  .scan-area {
    margin-bottom: 60rpx;
    position: relative;
    
    .camera {
      width: 500rpx;
      height: 600rpx;
      position: absolute;
      top: 0;
      left: 0;
      z-index: 1;
    }
    
    .scan-frame {
      width: 500rpx;
      height: 600rpx;
      position: relative;
      margin-bottom: 30rpx;
      z-index: 2;
      
      .corner {
        position: absolute;
        width: 50rpx;
        height: 50rpx;
        border-color: #4080ff;
        border-style: solid;
        border-width: 0;
        
        &.top-left {
          top: 0;
          left: 0;
          border-top-width: 6rpx;
          border-left-width: 6rpx;
        }
        
        &.top-right {
          top: 0;
          right: 0;
          border-top-width: 6rpx;
          border-right-width: 6rpx;
        }
        
        &.bottom-left {
          bottom: 0;
          left: 0;
          border-bottom-width: 6rpx;
          border-left-width: 6rpx;
        }
        
        &.bottom-right {
          bottom: 0;
          right: 0;
          border-bottom-width: 6rpx;
          border-right-width: 6rpx;
        }
      }
      
      .scan-line {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 4rpx;
        background: linear-gradient(to right, transparent, #4080ff, transparent);
        animation: scanAnimation 2s linear infinite;
      }
      
      .countdown-timer {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: 160rpx;
        height: 160rpx;
        border-radius: 50%;
        background: rgba(64, 128, 255, 0.4);
        display: flex;
        align-items: center;
        justify-content: center;
        z-index: 10;
        
        text {
          font-size: 80rpx;
          font-weight: bold;
          color: #fff;
          text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.3);
        }
      }
      
      .face-avatar {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: 240rpx;
        height: 240rpx;
        border-radius: 50%;
        overflow: hidden;
        border: 6rpx solid #4080ff;
        
        image {
          width: 100%;
          height: 100%;
          object-fit: cover;
        }
      }
    }
    
    .scan-tips {
      display: block;
      text-align: center;
      font-size: 32rpx;
      color: #333;
      z-index: 3;
      position: relative;
    }
    
    &.scanning {
      .scan-frame {
        .corner {
          border-color: #ffb74d;
        }
        
        .scan-line {
          background: linear-gradient(to right, transparent, #ffb74d, transparent);
        }
      }
      
      .scan-tips {
        color: #ffb74d;
      }
    }
    
    &.recognized {
      .scan-frame {
        .corner {
          border-color: #4caf50;
          border-width: 6rpx;
        }
        
        .face-avatar {
          border-color: #4caf50;
        }
      }
      
      .scan-tips {
        color: #4caf50;
        font-weight: bold;
      }
    }
    
    &.failed {
      .scan-frame {
        .corner {
          border-color: #4caf50;
        }
        
        .face-avatar {
          border-color: #4caf50;
        }
      }
      
      .scan-tips {
        color: #4caf50;
      }
    }
  }
  
  .action-btns {
    display: flex;
    justify-content: center;
    margin-bottom: 50rpx;
    
    .action-btn {
      min-width: 220rpx;
      height: 80rpx;
      line-height: 80rpx;
      text-align: center;
      border-radius: 40rpx;
      font-size: 32rpx;
      margin: 0 20rpx;
      
      &.primary {
        background: #4080ff;
        color: #fff;
      }
      
      &.cancel {
        background: #f5f5f5;
        color: #666;
      }
      
      &.retry {
        background: #ff9800;
        color: #fff;
      }
    }
  }
  
  .tips {
    margin-bottom: 60rpx;
    text-align: center;
    
    text {
      display: block;
      font-size: 28rpx;
      color: #999;
      line-height: 1.6;
    }
  }
  
  .switch-mode {
    text-align: center;
    
    text {
      font-size: 28rpx;
      color: #4080ff;
      text-decoration: underline;
    }
  }
}

@keyframes scanAnimation {
  0% {
    top: 0;
  }
  50% {
    top: 100%;
  }
  100% {
    top: 0;
  }
}
</style> 